package com.moss.cloud.common.flow.parser;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.moss.cloud.common.core.utils.BooleanHandel;
import com.moss.cloud.common.flow.enums.TaskType;
import com.moss.cloud.common.flow.model.Condition;
import com.moss.cloud.common.flow.model.ConditionField;
import com.moss.cloud.common.flow.model.NodeRelation;
import com.moss.cloud.common.flow.model.NodeTask;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 解析流程数据
 *
 * @author 瑾年
 * @date 2024年4月7日
 */
public class FlowParser {
    public static void main(String[] args) {
        String jsonStr = "{\"cells\":[{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"760cea0c-c220-4409-a3f3-ba8d1450737a\",\"zIndex\":-1,\"data\":{\"source\":\"node-start\",\"target\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\"},\"source\":{\"cell\":\"node-start\",\"port\":\"node-start-out\"},\"target\":{\"cell\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"port\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"fd156f5d-df4b-4b78-8ea0-3aa17b367488\",\"zIndex\":-1,\"data\":{\"source\":\"node-start\",\"target\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\"},\"source\":{\"cell\":\"node-start\",\"port\":\"node-start-out\"},\"target\":{\"cell\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"port\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"eea7a702-f70d-40dd-b513-308a62ec6d38\",\"zIndex\":-1,\"data\":{\"source\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"target\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\"},\"source\":{\"cell\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"port\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-out\"},\"target\":{\"cell\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"port\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"75f39ae6-21da-40bb-9211-1d09f05f616b\",\"zIndex\":-1,\"data\":{\"source\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"target\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\"},\"source\":{\"cell\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"port\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-out\"},\"target\":{\"cell\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"port\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"c08312e4-535c-4301-9288-03e8427efcda\",\"zIndex\":-1,\"data\":{\"source\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"target\":\"node-merge\"},\"source\":{\"cell\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"port\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-out\"},\"target\":{\"cell\":\"node-merge\",\"port\":\"node-merge-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"8a9eeb98-4949-4cb8-9290-2f85b8ce0901\",\"zIndex\":-1,\"data\":{\"source\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"target\":\"node-merge\"},\"source\":{\"cell\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"port\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-out\"},\"target\":{\"cell\":\"node-merge\",\"port\":\"node-merge-in\"}},{\"shape\":\"data-processing-curve\",\"connector\":{\"name\":\"curveConnector\"},\"attrs\":{\"line\":{\"stroke\":\"#3471F9\",\"strokeDasharray\":5,\"style\":{\"animation\":\"running-line 30s infinite linear\"}}},\"id\":\"60361d00-1c12-493f-8f35-ab7e6395e3fc\",\"zIndex\":-1,\"data\":{\"source\":\"node-merge\",\"target\":\"node-end\"},\"source\":{\"cell\":\"node-merge\",\"port\":\"node-merge-out\"},\"target\":{\"cell\":\"node-end\",\"port\":\"node-end-in\"}},{\"position\":{\"x\":-320,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"开始\",\"type\":\"START\",\"checkStatus\":\"sucess\",\"status\":\"success\"},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"node-start-out\",\"group\":\"out\"}]},\"id\":\"node-start\",\"zIndex\":1},{\"position\":{\"x\":-70,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"请假天数>3\",\"type\":\"CONDITION\",\"condition\":{\"field\":\"days\",\"conditionValue\":\"3\",\"term\":\">\",\"desc\":\"请假天数\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-in\",\"group\":\"in\"},{\"id\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df-out\",\"group\":\"out\"}]},\"id\":\"587f9e6f-ba63-4781-8ffb-eaf47aaed2df\",\"zIndex\":2,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":-70,\"y\":0},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"请假天数>=3\",\"type\":\"CONDITION\",\"condition\":{\"field\":\"days\",\"conditionValue\":\"3\",\"term\":\">=\",\"desc\":\"请假天数\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-in\",\"group\":\"in\"},{\"id\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127-out\",\"group\":\"out\"}]},\"id\":\"9a7027b6-d6e8-4d4e-b220-e256f5d81127\",\"zIndex\":3,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":180,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"部门经理审批\",\"type\":\"TASK\",\"headUser\":[101],\"ccToUser\":[101],\"nodeTaskEndTime\":null,\"reachEndTimePass\":false,\"sign\":\"OR\",\"condition\":{\"field\":\"\",\"conditionValue\":\"\",\"term\":\"\",\"desc\":\"\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-in\",\"group\":\"in\"},{\"id\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3-out\",\"group\":\"out\"}]},\"id\":\"1fcb687f-9075-4e6a-8ecb-4072b68998d3\",\"zIndex\":4,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":180,\"y\":0},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"组长审批\",\"type\":\"TASK\",\"headUser\":[102],\"ccToUser\":[101],\"nodeTaskEndTime\":null,\"reachEndTimePass\":false,\"sign\":\"OR\",\"condition\":{\"field\":\"\",\"conditionValue\":\"\",\"term\":\"\",\"desc\":\"\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-in\",\"group\":\"in\"},{\"id\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243-out\",\"group\":\"out\"}]},\"id\":\"98684ae0-11ec-44ff-a1f7-047ff21f8243\",\"zIndex\":5,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":430,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"人事审批\",\"type\":\"MERGE\",\"headUser\":[101],\"ccToUser\":[101],\"nodeTaskEndTime\":null,\"reachEndTimePass\":false,\"sign\":\"OR\",\"condition\":{\"field\":\"\",\"conditionValue\":\"\",\"term\":\"\",\"desc\":\"\"}},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"node-merge-in\",\"group\":\"in\"},{\"id\":\"node-merge-out\",\"group\":\"out\"}]},\"id\":\"node-merge\",\"zIndex\":6,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}},{\"position\":{\"x\":680,\"y\":-100},\"size\":{\"width\":212,\"height\":48},\"view\":\"vue-shape-view\",\"shape\":\"data-processing-dag-node\",\"data\":{\"name\":\"结束\",\"type\":\"END\"},\"ports\":{\"groups\":{\"in\":{\"position\":\"left\",\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}},\"out\":{\"position\":{\"name\":\"right\",\"args\":{\"dx\":-32}},\"attrs\":{\"circle\":{\"r\":4,\"magnet\":true,\"stroke\":\"transparent\",\"strokeWidth\":1,\"fill\":\"transparent\"}}}},\"items\":[{\"id\":\"node-end-in\",\"group\":\"in\"}]},\"id\":\"node-end\",\"zIndex\":7,\"tools\":{\"items\":[{\"name\":\"button-remove\",\"args\":{\"x\":200,\"y\":10}}]}}]}";
        System.out.println(relationList(jsonStr));
        System.out.println(nodeTasks(jsonStr));
        System.out.println(conditionFields(nodeTasks(jsonStr)));
    }

    /**
     * 解析任务关系
     *
     * @param json
     * @return
     */
    public static List<NodeRelation> relationList(String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        JSONArray relationsArray = jsonObject.getJSONArray("cells");
        List<NodeRelation> relationList = new ArrayList<>();
        relationsArray.forEach(item -> {
            JSONObject cell = (JSONObject) item;
            String shape = cell.getString("shape");
            BooleanHandel.isTrue(shape.equals("data-processing-curve")).trueHandle(() -> {
                String source = cell.getJSONObject("data").getString("source");
                String target = cell.getJSONObject("data").getString("target");
                NodeRelation relation = new NodeRelation();
                relation.setSource(source);
                relation.setTarget(target);
                relationList.add(relation);
            });
        });
        return relationList;
    }

    /**
     * 解析任务节点
     *
     * @param json
     * @return
     */
    public static List<NodeTask> nodeTasks(String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        JSONArray relationsArray = jsonObject.getJSONArray("cells");
        List<NodeTask> nodeTasks = new ArrayList<>();
        relationsArray.forEach(item -> {
            JSONObject cell = (JSONObject) item;
            String shape = cell.getString("shape");
            BooleanHandel.isTrue(shape.equals("data-processing-dag-node")).trueHandle(() -> {
                NodeTask nodeTask = new NodeTask();
                parserTaskId(cell, nodeTask);
                parserName(cell, nodeTask);
                parserType(cell, nodeTask);
                parserHeadUsers(cell, nodeTask);
                parserCcToUsers(cell, nodeTask);
                parserNodeTaskEndTime(cell, nodeTask);
                parserReachEndTimePass(cell, nodeTask);
                parserSign(cell, nodeTask);
                parserCondition(cell, nodeTask);
                nodeTasks.add(nodeTask);
            });
        });
        return nodeTasks;
    }

    /**
     * 解析任务条件字段
     *
     * @param nodeTasks
     * @return
     */
    public static List<ConditionField> conditionFields(List<NodeTask> nodeTasks) {
        return CollectionUtils.isNotEmpty(nodeTasks) ? nodeTasks.stream()
                .filter(item -> item.getType().equals(TaskType.CONDITION.getType()))
                .map(item -> {
                    ConditionField conditionField = new ConditionField();
                    conditionField.setField(item.getCondition().getField());
                    return conditionField;
                })
                .distinct()
                .collect(Collectors.toList()) : Collections.emptyList();
    }

    /**
     * 解析任务节点ID
     *
     * @param cell
     * @return
     */
    private static void parserTaskId(JSONObject cell, NodeTask nodeTask) {
        nodeTask.setTaskId(cell.getString("id"));
    }

    /**
     * 解析任务名称
     *
     * @param cell
     * @return
     */
    private static void parserName(JSONObject cell, NodeTask nodeTask) {
        nodeTask.setName(cell.getJSONObject("data").getString("name"));
    }

    /**
     * 解析任务类型
     *
     * @param cell
     * @param nodeTask
     */
    private static void parserType(JSONObject cell, NodeTask nodeTask) {
        nodeTask.setType(cell.getJSONObject("data").getString("type"));
    }

    /**
     * 解析负责人
     *
     * @param cell
     * @param nodeTask
     */
    private static void parserHeadUsers(JSONObject cell, NodeTask nodeTask) {
        List<Long> headUsers = cell.getJSONObject("data").containsKey("headUser") ?
                cell.getJSONObject("data").getList("headUser", Long.class) : Collections.emptyList();
        nodeTask.setHeadUsers(headUsers);
    }

    /**
     * 解析抄送人
     *
     * @param cell
     * @param nodeTask
     */
    private static void parserCcToUsers(JSONObject cell, NodeTask nodeTask) {
        List<Long> ccToUsers = cell.getJSONObject("data").containsKey("ccToUser") ?
                cell.getJSONObject("data").getList("ccToUser", Long.class) : Collections.emptyList();
        nodeTask.setCcToUsers(ccToUsers);
    }

    /**
     * 解析任务结束时间
     *
     * @param cell
     * @param nodeTask
     */
    private static void parserNodeTaskEndTime(JSONObject cell, NodeTask nodeTask) {
        Long nodeTaskEndTime = cell.getJSONObject("data").containsKey("nodeTaskEndTime") ?
                cell.getJSONObject("data").getLong("nodeTaskEndTime") : null;
        nodeTask.setNodeTaskEndTime(nodeTaskEndTime);
    }

    /**
     * 解析任务结束是否自动通过状态
     *
     * @param cell
     * @param nodeTask
     */
    private static void parserReachEndTimePass(JSONObject cell, NodeTask nodeTask) {
        Boolean reachEndTimePass = cell.getJSONObject("data").containsKey("reachEndTimePass") ?
                cell.getJSONObject("data").getBoolean("reachEndTimePass") : Boolean.FALSE;
        nodeTask.setReachEndTimePass(reachEndTimePass);
    }

    /**
     * 解析任务批复类型(会签/或签)
     *
     * @param cell
     * @param nodeTask
     */
    private static void parserSign(JSONObject cell, NodeTask nodeTask) {
        String sign = cell.getJSONObject("data").containsKey("sign") ?
                cell.getJSONObject("data").getString("sign") : StringUtils.EMPTY;
        nodeTask.setSign(sign);
    }

    /**
     * 解析任务条件对象
     *
     * @param cell
     * @param nodeTask
     */
    private static void parserCondition(JSONObject cell, NodeTask nodeTask) {
        Condition condition = cell.getJSONObject("data").containsKey("condition") ?
                cell.getJSONObject("data").getObject("condition", Condition.class) : null;
        nodeTask.setCondition(condition);
    }
}
